package in.ac.iitb.cse.nlp.postagger.data;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class DebugConsole {
	TransitionMatrix tm;
	EmissionMatrix em;
	List<String> tagSet;
	TableCreator tc;
	int whichHMM=0;
	int isCalc=0;

	public void start(TransitionMatrix t, EmissionMatrix e, List<String> ts) throws IOException
	{
		tm =t;
		em =e;
		tagSet = ts;
		run();
	}
	
	public void start() throws IOException 
	{
		tc = newTraining();
		run();
	}
	
	public void run() throws IOException
	{
		String line;
		printInfo();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		List<String> bestProbTagSeq = null;
		do
		{
			System.out.print(">");
			line = br.readLine();
			
			if(line.startsWith("exit"))
					break;
			else if(line.startsWith(":") == false)
			{
				bestProbTagSeq = tagSentence(line, br);
				bestProbTagSeq = null;
			}else
			{
				line = line.trim();
				line = line.replaceFirst(":", "");
				line = line.trim();
				
				if( line.startsWith("emiignore")==true){
					if ( Config.isEmiIgnore == false ){
						System.out.println("Unknown word Emission Prob will be ignored");
						Config.isEmiIgnore = true;
					}else{
						System.out.println("Unknown word Emission Prob will not be ignored");
						Config.isEmiIgnore = false;						
					}
				}else if( line.startsWith("emilap")==true){
					if ( Config.isEmiLapSmoothing == false ){
						System.out.println("Laplace Smoothing for ET is in enabled");
						Config.isEmiLapSmoothing = true;
					}else{
						System.out.println("Laplace Smoothing for ET is in disabled");
						Config.isEmiLapSmoothing = false;						
					}
				}else if( line.startsWith("translap")==true){
					if ( Config.isTransLapSmoothing == false ){
						System.out.println("Laplace Smoothing for TT is in enabled");
						Config.isTransLapSmoothing = true;
					}else{
						System.out.println("Laplace Smoothing for TT is in disabled");
						Config.isTransLapSmoothing = false;						
					}
				}else if( line.startsWith("wt")==true){
					line = line.replaceFirst("wt", "");
					line = line.trim();
					String s[]= line.split(" ");
					if(s.length>=2) printWordTag(s[0], s[1]);
				}
				else if( line.startsWith("wi")==true)
				{
					line = line.replaceFirst("wi", "");
					line = line.trim();
					printWordInfo(line);
				}
				else if( line.startsWith("wc")==true)
				{
					line = line.replaceFirst("wc", "");
					line = line.trim();
					printWordCount(line);
				}
				else if( line.startsWith("tt")==true)
				{
					line = line.replaceFirst("tt", "");
					line = line.trim();
					String s[]= line.split(" ");
					if(s.length>=2) printTagTag(s[0], s[1]);
				}
				else if( line.startsWith("tc")==true){
					line = line.replaceFirst("tc", "");
					line = line.trim();
					printTagCount(line);
				}
				else if( line.startsWith("st")==true){
					line = line.replaceFirst("st", "");
					line = line.trim();
					printProbState(line);
				}else if( line.startsWith("bi")==true){
					Config.isBigram = true;
					Config.isTrigram = false;
					if( Config.isBigramInUse == false )
					{
						System.out.println("Set to bigram tagger");
						Config.isTrigramInUse = false;
						Config.isBigramInUse = true;
						newTraining();
					}else
					{
						System.out.println("Bigram tagger in use");						
					}
				}else if( line.startsWith("tri")==true){
					Config.isTrigram = true;
					Config.isBigram = false;
					if( Config.isTrigramInUse == false )
					{
						System.out.println("Set to Trigram tagger");
						Config.isTrigramInUse = true;
						Config.isBigramInUse = false;
						newTraining();
					}else
					{
						System.out.println("Trigram tagger in use");						
					}
				}else if( line.startsWith("d")==true){
					if ( Config.isDebug == true) {
						Config.isDebug = true;
						System.out.println("Debug on.");
					}else {
						Config.isDebug = false;
						System.out.println("Debug off.");						
					}
				}else{
					Config.isBigram = false;
					System.out.println("Invalid Input.");
				}
				
			}
		}while(true);
		System.out.println("\nBye Bye\n");		
	}
	
	public List<String> tagSentence(String sentence,BufferedReader br) throws IOException
	{
		
		String[] split = sentence.split(" ");
		List<String> input = new ArrayList<String>();
		for(String string : split)
		{
			if( string.isEmpty() == false)
			input.add(string);
		}
		
		if (input.size() <3)
			return null;
	
		//System.out.println("\n Observation Seq : "+input.toString());
		
		HMM vhmm = null;
		if( Config.isTrigramInUse ){
			vhmm = new TriViterbiHMM();
			System.out.println("Using Trigram.");
		}else if(Config.isBigramInUse){
			vhmm = new BiViterbiHMM();
			System.out.println("Using Bigram.");
		}
		vhmm.init(new ArrayList<String>(tagSet),tm,em);
		List<String> bestProbTagSeq = vhmm.bestProbTagSeq(input);
		if(bestProbTagSeq != null)
		{
			System.out.println("\n----------------------------------");
			for(int i=0;i<bestProbTagSeq.size();i++)
				System.out.print(bestProbTagSeq.get(i)+"_"+input.get(i)+" ");
			System.out.println("\n----------------------------------");
			if( Config.isDebug == true )
			{
				System.out.print("Do you want to see calculations ?[Y/N]");
				String l = br.readLine();
				if(l.equalsIgnoreCase("y")==true)
				{
					printProbState(input, bestProbTagSeq);
					System.out.println("----------------------------------");
				}
			}
		}
		return bestProbTagSeq;
	}
	
	private void printInfo()
	{
		System.out.println("\n\n\n");
		System.out.println("System is ready..");
		System.out.println("Enter sentence to be tagged.Example \"I love this class and subject\"..");
		System.out.println("one space between two words");
		System.out.println("Please enter word exit to quit ..");
	}
	
	public void printTagTag(String tag1, String tag2)
	{
		Double p;
		
		Tag t1 = DataMaps.tags.get(tag1);
		Tag t2 = DataMaps.tags.get(tag2);
		
		if( null == t1)
		{
			System.out.println( "TAG "+tag1+" not found ");
			return;
		}
		if( null == t2)
		{
			System.out.println( "TAG "+tag2+" not found ");
			return;
		}
		
		p = tm.getProbability(tag2, tag1);//Ulta
		//PROB (tag2/tag1)
		System.out.println("");
		System.out.println("Prob(T="+tag1+"/T="+tag2+")====>"+p);
		
		//COUNT
		System.out.println("");
		System.out.println("n("+tag1+","+tag2+" ) ====> "+tm.getCount(tag2, tag1));//Ulta
		System.out.println("n("+tag1+") ====> "+t1.getCount());
		System.out.println("n("+tag2+") ====> "+t2.getCount());		
	}

	public void printTagCount(String tag1)
	{
		Tag t1 = DataMaps.tags.get(tag1);
		if( null == t1)
		{
			System.out.println( "TAG "+tag1+" not found ");
			return;
		}		
		System.out.println("");
		System.out.println("TAG n("+tag1+") ====> "+t1.getCount());
	}

	public void printWordInfo(String word)
	{		
		Word w = DataMaps.words.get(word);
		if( null == w)
		{
			System.out.println( word+" not found ");
			return;
		}
		for(int i=0;i<tagSet.size();i++)
		{
			String tag2 = tagSet.get(i);
			if(em.getCount(tag2, word) !=0)
			System.out.println("n("+word+","+tag2+" ) ====> "+em.getCount(tag2, word));//Ulta
		}
		//COUNT
		System.out.println("");
		System.out.println("n("+word+") ====> "+w.getCount());
	}

	public void printWordTag(String word, String tag2)
	{
		Double p;
		
		Tag t2 = DataMaps.tags.get(tag2);
		Word w = DataMaps.words.get(word);
		if( null == w)
		{
			System.out.println( word+" not found ");
			return;
		}
		if( null == t2)
		{
			System.out.println( tag2+" not found ");
			return;
		}		
		p = em.getProbability(tag2, word);//Ulta
		//PROB (tag2/tag1)
		System.out.println("");
		System.out.println("Prob(T="+word+"/T="+tag2+") ====> "+p);
		
		//COUNT
		System.out.println("");
		System.out.println("n("+word+","+tag2+" ) ====> "+em.getCount(tag2, word));//Ulta
		System.out.println("n("+word+") ====> "+w.getCount());
		System.out.println("n("+tag2+") ====> "+t2.getCount());		
	}

	public void printWordCount(String word)
	{
		Word w = DataMaps.words.get(word);
		if( null == w)
		{
			System.out.println( word+" not found ");
			return;
		}
		System.out.println("n("+word+") ====> "+w.getCount());
	}

	public  void printProbState(String line)
	{
		//(^ who are you $ | ^ TAG1 TAG2 
		List <String> wordseq = new ArrayList<String>();
		List <String> tagseq = new ArrayList<String>();
		
		String[] split = line.split(" ");

		int total = split.length;
		int i=1;
		if( split[0].contains("_") == true )
		{
			for(String string : split)
			{
				if(string.isEmpty() == false)
				{	
					String []seq = string.split("_");
					if(seq.length >= 2)
					{
							wordseq.add(seq[1]);
							tagseq.add(seq[0]);
							Tag t = DataMaps.tags.get(seq[0]);
							if( seq[0].equals("$")==false && t == null)
							{
								System.out.println("Sorry the tag [["+seq[0]+"]] seems to be invalid");
								System.out.println("Please provide correct input");
								return;
							}					
					}
				}
			}
			
		}
		else
		{
			for(String string : split)
			{
				if(string.isEmpty() == false)
				{	
					if(i <= total/2)
					{
						wordseq.add(string);
					}else
					{
						tagseq.add(string);
						Tag t = DataMaps.tags.get(string);
						if( string.equals("$")==false && t == null)
						{
							System.out.println("Sorry the tag [["+string+"]] seems to be invalid");
							System.out.println("Please provide correct input");
							return;
						}					
					}
					i++;
				}
			}
		}				
		if( wordseq.size() != tagseq.size() )
		{
			System.out.println("WordSEQ and TagSEQ has different length. it should not be");
			System.out.println("Please provide correct input");
			return;
		}

		//System.out.println("\nWordSEQ " + wordseq.toString());
		//System.out.println("TagSEQ " + tagseq.toString());
		
		printProbState(wordseq, tagseq);
	}
	
	public void printProbState(List <String> Sentence, List <String> tagseq)
	{		
		if(Sentence.get(0).equals("^") == false) Sentence.add(0, "^");
		if(tagseq.get(0).equals("^") == false) tagseq.add(0, "^");
		if(Sentence.get(Sentence.size()-1).equals("$") == false) Sentence.add( "$");
		if(tagseq.get(tagseq.size()-1).equals("$") == false) tagseq.add("$");
		
		System.out.println("\nPROBABILITY (" + tagseq.toString() +" / " + Sentence.toString() +" ) ===> \n");
		
		HMM vhmm = new BiViterbiHMM();
		vhmm.init(new ArrayList<String>(tagSet),tm,em);
		Double d = vhmm.ProbTagSeq(tagseq,Sentence);
		System.out.println("Final Probablity ===> "+d);
		System.out.println("");
	}
	
	public TableCreator newTraining()
	{
		TableCreator tc = null;
		if( Config.isTrigram )
		{
			tc = new TriTableCreator();
		}
		else
			tc = new BiTableCreator();
		//tableCreator.go();
		/*
		tableCreator.processLine("PNP_I VVB_will PUN_. PNP_I VVB_will PUN_.");
		System.out.println(TableCreator.transitionMatrix.toString());
		List<String> b =tableCreator.tagSentence("^ I will $");
		System.out.println(b.toString());
		*/
		DataMaps.tags.clear();
		DataMaps.words.clear();
		
		tc.goDir("", "corpus");
		
		tm =tc.transitionMatrix;
		em =tc.emissionMatrix;
		tagSet = new ArrayList<String>(tc.tagSet) ;
		
		Config.nTotalTags = tc.tagSet.size();
		if(Config.isTrigram)
		TriViterbiHMM.calcSmoothingFactors(tc.transitionMatrix, new ArrayList<String>(tc.tagSet));
		
		return tc;
	}
	
}
